import { getTypeof } from './typeofs'

enum Methods {
    a = 'local',
    b = 'session'
}

interface KeyValue {
    key: string
    value: string | number,
    data?: any
}

// 根据index查询
function findIndex(data: Array<any>, arg: KeyValue): Array<any> {
    const index = data.findIndex(item => (item as any)[arg.key] === arg.value)
    if(index < 0) return []
    return data[index]
}

// 根据条件查询数据
function findArray(data: Array<any>, arg: object): Array<any> {    
    const keys: Array<any> = Object.keys(arg)
    // 没有值或者没有参数返回空数组
    if(!keys.length || !data.length) return []
    // 多参数查询，遍历参数有一项不符合则为false, 全符合添加到待返回数组中
    let arr: Array<any> = []
    data.forEach(item => {
        let res = true
        keys.forEach(val => {
            if((item as any)[val] !== (arg as any)[val]) res = false
        })
        if(res) arr.push(item)
    })
    return arr
}

// 添加对象
function addObjectItem() {
    
}

// 添加数组
function addArrayItem() {

}

// 更新对象
function updateObject(data: any, arg: KeyValue): object {
    let result: any = {...data}
    result[arg.key] = arg.value
    // result.hasOwnProperty(arg.key) 判断key是否存在
    return result
}

// 更新数组
// 数组需要设置唯一key, 根据key确定数组，根据data值更新
function updateArray( data: Array<any>, arg: KeyValue): Array<any> | any {
    const type = getTypeof(arg)
    if(type !== 'object') return
    const index: number = data.findIndex(item => item[arg.key] === arg.value)
    if(index < 0) {
        data.unshift(arg.data)
    } else {
        data[index] = arg.data
    }

    return data
}

interface AddDefaults<D = any> {

}

interface AddObject<T = any> extends AddDefaults {
    key: string
    value: any
}


class Storage {
    private storage: any
    constructor(key?: string) {
        this.storage = (window as any)[`${key}Storage`]
    }
    private set(key: string, val: any): void {
        if(typeof val === undefined) return this.remove(key)
        const type = getTypeof(val)
        const data = type=== 'string' ? val : JSON.stringify(val)
        this.storage.setItem(key, data)
    }
    // 获取数据
    get(name: string): any {
        const data: string = this.storage.getItem(name)
        try { return JSON.parse(data) }
        catch (e) { return data }
    }
    find(key: string, args: any): any {
        const type = 'array'
        const data = [{
            name: 'wang',
            age: 18
        }, {
            name: 'zhao',
            age: 19
        }, {
            name: 'wang',
            age: 19
        },{
            name: 'wang',
            age: 19,
            sex: 1
        }]
        if(type === 'array') return findArray(data, args)
        return
        // const type = getTypeof(args)
        // const data = this.get(key)
        // if(type === 'array') return findArray(data, args)
        // if(type === 'object') return findObject(data, args)
        // return this.get(key)
    }
    filter() {

    }
    /**
     * 添加数据
     * 第一个参数
     * 处理的key名
     * 第二个参数
     * 字符串：有内容替换，无内容设置
     * 对象：第二个参数为key,value,添加为新属性
     * 数组：将第二个参数添加至第0位
     * 其他：转为字符串替换
     * 第三个参数
     * 删除的项目
     * @param key 名称
     * @param val 内容
     * @param del 删除
     */
    add(key: string, val: any) {
        const data = this.get(key)
        if(!data) this.set(key, val)
        const type: string = getTypeof(data)
        if(type !== 'array' && type !== 'object') {
            this.set(key, val)
        } else {
            if(type === 'array') {
                data.unshift(val)
            } else {
                data[val.key] = val.value
            }
            this.set(key, data)
        }
    }    
    // 如果是数组则更新数组，否则更新自身内容
    update(key: string, val: any): void {
        const data = this.get(key)
        const keyType = getTypeof(data)
        if(keyType !== 'array' && keyType !== 'object') {
            this.set(key, val)
        } else {
            if(keyType === 'object') {
                const res = updateObject(data, val)
                this.set(key, res)
            } else {
                updateArray(data, val)
            }
        }
    }
    /**
     * 删除
     * 删除对象
     * 第二个参数为对象要删除的key
     * 删除数组
     * 第二个参数为要删除的数组下标，正数从左往右，负数从右往左
     * @param key 
     * @param val 
     * @returns void
     */
    delete(key:string, val: any | number): void {
        const data = this.get(key)
        if(!data) return
        const type = getTypeof(data)
        if(type === 'object') {
            delete data[val]
        } else {
            data.splice(val, 1)
        }
        this.set(key, data)
    }
    /**
     * 批量删除
     */
    deleteBetch() {

    }
    remove(key: string): void {
        this.storage.removeItem(key)
    }
    clear(): void {
        this.storage.clear()
    }
}

export const Local = class extends Storage {
    constructor() { 
        super(Methods.a)
    }
}
export const Session = class extends Storage {
    constructor() { 
        super(Methods.b)
    }
}